import * as _ from 'lodash';
import { NodeModel } from '../page/model/Model';
import { Point, Range } from '../reducer/const';

export const parseEventTarget = (e) => {
    let target;
    if (e.type === 'touchstart' || e.type === 'touchmove' || e.type === 'touchend') {
        target = e.targetTouches[0];
    } else if (e.type === 'mousedown' || e.type === 'mousemove' || e.type === 'mouseup') {
        target = e.nativeEvent;
    }
    return target || {};
};

export const checkPointInRange = (range: Range, point: Point): boolean => {
    if (!point) {
        return false;
    }
    const {x, y} = point;
    return range.x <= x && x <= (range.x + range.width) && range.y <= y && y <= (range.y + range.height);
};

export const getValidNodeRange = (): Range => {
    const range: Range = { x: 80, y: 32, width: document.body.clientWidth - 80 - 200, height: document.body.clientHeight };
    return range;
};

export const inValidDragNodeRange = (point: Point): boolean => {
    const range: Range = getValidNodeRange();
    return checkPointInRange(range, point);
};

export const getRangeByPoint = (ranges: NodeModel[], extendId: string, pointA: Point, pointB?: Point, pointC?: Point, pointD?: Point): NodeModel => {
    let result: NodeModel = _.find(ranges, (item) => item.id !== extendId && (checkPointInRange(item.range, pointA) || checkPointInRange(item.range, pointB) || checkPointInRange(item.range, pointC) || checkPointInRange(item.range, pointD)));
    return result;
};

export const getRangeOverlap = (ranges: NodeModel[], extendId: string, range: Range): NodeModel => {
    const pointA: Point = {
        x: range.x,
        y: range.y
    };
    const pointB: Point = {
        x: range.x + range.width,
        y: range.y
    };
    const pointC: Point = {
        x: range.x,
        y: range.y + range.height
    };
    const pointD: Point = {
        x: range.x + range.width,
        y: range.y + range.height
    };
    const overlapNode: NodeModel = getRangeByPoint(ranges, extendId, pointA, pointB, pointC, pointD);
    return overlapNode;
};


export const getSuggestRanges = (overlapNode: NodeModel, validRange: Range, offsetX: number = 50, offsetY: number = 10): Range[] => {
    const suggestRanges: any[] = [];
    const { range } = overlapNode;
    // t
    suggestRanges.push({
        sort: validRange.y - range.y,
        x: validRange.x,
        y: range.y - offsetY - validRange.height,
        width: validRange.width,
        height: validRange.height
    });
    // r
    suggestRanges.push({
        sort: range.x + range.width - validRange.x,
        x: range.x + range.width + offsetX,
        y: validRange.y,
        width: validRange.width,
        height: validRange.height
    });
    // b
    suggestRanges.push({
        sort: range.y + range.height - validRange.y,
        x: validRange.x,
        y: range.y + range.height + offsetY,
        width: validRange.width,
        height: validRange.height
    });
    // l
    suggestRanges.push({
        sort: validRange.x - range.x,
        x: validRange.x - offsetX - validRange.width,
        y: validRange.y,
        width: validRange.width,
        height: validRange.height
    });
    suggestRanges.sort((a, b) => {
        return a.sort - b.sort;
    });
    return suggestRanges;
};

export const getNodeSuggestRange = (node: NodeModel[], extendId: string, range: Range) => {
    if (!node || !range) {
        return null;
    }
    let overlapNode: NodeModel = getRangeOverlap(node, extendId, range);
    let offsetX = 50;
    let offsetY = 50;
    let suggestFlag: boolean = !(overlapNode === null || overlapNode === undefined);
    while (suggestFlag && offsetX < 1000) {
        const suggestRanges: any[] = getSuggestRanges(overlapNode, range, offsetX, offsetY);
        let counter: number = 0;
        while (counter < 4) {
            const suggestRange: Range = suggestRanges[counter];
            overlapNode = getRangeOverlap(node, extendId, suggestRange);
            if (overlapNode === null || overlapNode === undefined) {
                suggestFlag = false;
                return suggestRange;
            }
            counter++;
        }
        offsetX = offsetX + 50;
        offsetY = offsetY + 10;
    }
    return null;
};

export class PathString {
    private path: string[] = new Array<string>();

    public M(point: Point | number, y?: number): PathString {
        if (point instanceof Point) {
            this.path.push(`M${point.x} ${point.y} `);
        } else {
            this.path.push(`M${point} ${y} `);
        }
        return this;
    }
    public L(point: Point | number, y?: number): PathString {
        if (point instanceof Point) {
            this.path.push(`L${point.x} ${point.y} `);
        } else {
            this.path.push(`L${point} ${y} `);
        }
        return this;
    }
    public Z(): PathString {
        this.path.push(`Z`);
        return this;
    }
    public toString(): string {
        return this.path.join('');
    }
}
